package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.DmcYingShiMonitorMapper;
import com.csun.cmny.provider.device.yingshi.YingShiUtils;
import com.csun.cmny.provider.device.yingshi.entity.YingShiDeviceCameraVo;
import com.csun.cmny.provider.device.yingshi.entity.YingShiUrlVo;
import com.csun.cmny.provider.exceptions.DmcBizException;
import com.csun.cmny.provider.model.domain.DmcYingShiConfig;
import com.csun.cmny.provider.model.domain.DmcYingShiMonitor;
import com.csun.cmny.provider.model.dto.yingshi.YingShiMonitorQueryDto;
import com.csun.cmny.provider.model.dto.yingshi.YingShiPlayerDto;
import com.csun.cmny.provider.model.dto.yingshi.YingshiMonitorEditDto;
import com.csun.cmny.provider.model.enums.device.DeviceStatusEnum;
import com.csun.cmny.provider.model.vo.yingshi.YingShiMonitorVo;
import com.csun.cmny.provider.model.vo.yingshi.YingShiPlayerVo;
import com.csun.cmny.provider.service.DmcYingShiChannelService;
import com.csun.cmny.provider.service.DmcYingShiConfigService;
import com.csun.cmny.provider.service.DmcYingShiMonitorService;
import com.csun.cmny.provider.utils.DateUtil;
import com.csun.cmny.util.PublicUtil;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2021/11/8 13:33
 * @Description: 萤石摄像头监控管理
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class DmcYingShiMonitorServiceImpl extends BaseService<DmcYingShiMonitor> implements DmcYingShiMonitorService {

    @Resource
    private DmcYingShiMonitorMapper dmcYingShiMonitorMapper;
    @Resource
    private DmcYingShiChannelService dmcYingShiChannelService;
    @Resource
    private DmcYingShiConfigService dmcYingShiConfigService;
    @Resource
    private YingShiUtils yingShiUtils;

    /**
     * 获取萤石摄像头监控列表
     *
     * @param yingShiMonitorQueryDto    the ying shi monitor query dto
     *
     * @return  the ying shi monitor vo list.
     */
    @Override
    public List<YingShiMonitorVo> queryListWithPage(YingShiMonitorQueryDto yingShiMonitorQueryDto) {

        PageHelper.startPage(yingShiMonitorQueryDto.getPageNum(), yingShiMonitorQueryDto.getPageSize());

        List<YingShiMonitorVo> yingShiMonitorVoList = dmcYingShiMonitorMapper.queryListWithPage(yingShiMonitorQueryDto);

        Map<Long, Map<Integer, YingShiDeviceCameraVo>> cameraMap = getChannelStatus(yingShiMonitorVoList);

        for (YingShiMonitorVo vo : yingShiMonitorVoList) {
            vo.setStatus(DeviceStatusEnum.OFFLINE.getKey());
            Map<Integer, YingShiDeviceCameraVo> cameraVo = cameraMap.get(vo.getDeviceId());
            if (PublicUtil.isNotEmpty(cameraVo)) {
                YingShiDeviceCameraVo channelVo = cameraVo.get(vo.getChannelNo());
                if (PublicUtil.isNotEmpty(channelVo) && channelVo.getStatus().equals(1)) {    // 在线
                    vo.setStatus(DeviceStatusEnum.ONLINE.getKey());
                }
            }
        }

        return yingShiMonitorVoList;
    }

    /**
     * 添加萤石摄像头通道监控
     *
     * @param channelId     the channel id
     * @param loginAuthDto  the login auth dto
     *
     * @return  the int.
     */
    @Override
    public Integer addSelect(Long channelId, LoginAuthDto loginAuthDto) {

        // 获取摄像头通道信息
        YingShiMonitorVo yingShiMonitorVo = dmcYingShiChannelService.selectByChannelId(channelId);
        if (PublicUtil.isEmpty(yingShiMonitorVo)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622014);
        }

        // 查询是否已经存在
        DmcYingShiMonitor dmcYingShiMonitor = dmcYingShiMonitorMapper.selectByPrimaryKey(channelId);
        if (PublicUtil.isNotEmpty(dmcYingShiMonitor)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622013);
        }

        // 获取序号
        Integer number = dmcYingShiMonitorMapper.selectNumber();
        if (PublicUtil.isEmpty(number)) {
            number = 1;
        }

        dmcYingShiMonitor = new DmcYingShiMonitor();
        dmcYingShiMonitor.setId(channelId);
        dmcYingShiMonitor.setChannelNo(yingShiMonitorVo.getChannelNo());
        dmcYingShiMonitor.setChannelName(yingShiMonitorVo.getChannelName());
        dmcYingShiMonitor.setChannelLocation(yingShiMonitorVo.getChannelLocation());
        dmcYingShiMonitor.setDeviceId(yingShiMonitorVo.getDeviceId());
        dmcYingShiMonitor.setDeviceNo(yingShiMonitorVo.getDeviceNo());
        dmcYingShiMonitor.setCode(yingShiMonitorVo.getCode());
        dmcYingShiMonitor.setGroupId(loginAuthDto.getGroupId());
        dmcYingShiMonitor.setNumber(number);

        dmcYingShiMonitor.setUpdateInfo(loginAuthDto);

        return dmcYingShiMonitorMapper.insertSelective(dmcYingShiMonitor);
    }

    /**
     * 添加萤石摄像头通道监控
     *
     * @param channelIdList the channel id list
     * @param loginAuthDto  the login auth dto
     *
     * @return  the int.
     */
    @Override
    public Integer save(List<Long> channelIdList, LoginAuthDto loginAuthDto) {

        int result = 0;

        // 删除已经移除的通道
        Map<Long, Long> channelIdMap = Maps.newHashMap();
        for (Long id : channelIdList) {
            channelIdMap.put(id, id);
        }

        DmcYingShiMonitor dmcYingShiMonitorQuery = new DmcYingShiMonitor();
        dmcYingShiMonitorQuery.setGroupId(loginAuthDto.getGroupId());
        List<DmcYingShiMonitor> dmcYingShiMonitorList = dmcYingShiMonitorMapper.select(dmcYingShiMonitorQuery);
        for (DmcYingShiMonitor vo : dmcYingShiMonitorList) {
            if (PublicUtil.isEmpty(channelIdMap.get(vo.getId()))) {
                result += dmcYingShiMonitorMapper.deleteByPrimaryKey(vo.getId());
            }
        }

        Iterator<Long> iterator = channelIdList.iterator();
        while (iterator.hasNext()) {
            Long channelId = iterator.next();
            // 查询是否已经存在
            DmcYingShiMonitor dmcYingShiMonitor = dmcYingShiMonitorMapper.selectByPrimaryKey(channelId);
            if (PublicUtil.isNotEmpty(dmcYingShiMonitor)) {
                iterator.remove();
            }
        }

        for (Long channelId : channelIdList) {
            // 获取摄像头通道信息
            YingShiMonitorVo yingShiMonitorVo = dmcYingShiChannelService.selectByChannelId(channelId);
            if (PublicUtil.isEmpty(yingShiMonitorVo)) {
                throw new DmcBizException(ErrorCodeEnum.DMC100622014);
            }

            // 获取序号
            Integer number = dmcYingShiMonitorMapper.selectNumber();
            if (PublicUtil.isEmpty(number)) {
                number = 1;
            } else {
                number++;
            }

            DmcYingShiMonitor dmcYingShiMonitor = new DmcYingShiMonitor();
            dmcYingShiMonitor.setId(channelId);
            dmcYingShiMonitor.setChannelNo(yingShiMonitorVo.getChannelNo());
            dmcYingShiMonitor.setChannelName(yingShiMonitorVo.getChannelName());
            dmcYingShiMonitor.setChannelLocation(yingShiMonitorVo.getChannelLocation());
            dmcYingShiMonitor.setDeviceId(yingShiMonitorVo.getDeviceId());
            dmcYingShiMonitor.setDeviceNo(yingShiMonitorVo.getDeviceNo());
            dmcYingShiMonitor.setCode(yingShiMonitorVo.getCode());
            dmcYingShiMonitor.setGroupId(loginAuthDto.getGroupId());
            dmcYingShiMonitor.setNumber(number);

            dmcYingShiMonitor.setUpdateInfo(loginAuthDto);

            result += dmcYingShiMonitorMapper.insertSelective(dmcYingShiMonitor);
        }

        return result;
    }

    @Override
    public Integer edit(YingshiMonitorEditDto yingshiMonitorEditDto, LoginAuthDto loginAuthDto) {

        // 查询是否已经存在
        DmcYingShiMonitor dmcYingShiMonitor = dmcYingShiMonitorMapper
                .selectByPrimaryKey(yingshiMonitorEditDto.getId());

        if (PublicUtil.isEmpty(dmcYingShiMonitor)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622014);
        }

        dmcYingShiMonitor.setNumber(yingshiMonitorEditDto.getNumber());
        dmcYingShiMonitor.setUpdateInfo(loginAuthDto);

        return dmcYingShiMonitorMapper.updateByPrimaryKeySelective(dmcYingShiMonitor);
    }

    @Override
    public Integer deleteById(Long id) {

        return dmcYingShiMonitorMapper.deleteByPrimaryKey(id);
    }

    /**
     * 获取萤石摄像头视频监控地址
     *
     * @param groupIdList   the group id list
     *
     * @return  the ying shi player vo list.
     */
    @Override
    public List<YingShiPlayerVo> queryPlayList(List<Long> groupIdList) {

        List<YingShiPlayerVo> yingShiPlayerVoList = Lists.newArrayList();

        YingShiMonitorQueryDto yingShiMonitorQueryDto = new YingShiMonitorQueryDto();
        yingShiMonitorQueryDto.setGroupIdList(groupIdList);

        List<YingShiMonitorVo> yingShiMonitorVoList = dmcYingShiMonitorMapper.queryListWithPage(yingShiMonitorQueryDto);
        for (YingShiMonitorVo vo : yingShiMonitorVoList) {
            // 获取token
            DmcYingShiConfig dmcYingShiConfig = dmcYingShiConfigService.selectByKey(vo.getGroupId());
            if (PublicUtil.isNotEmpty(dmcYingShiConfig)) {
                YingShiPlayerDto yingShiPlayerDto = new YingShiPlayerDto();
                yingShiPlayerDto.setAccessToken(dmcYingShiConfig.getAccessToken());
                yingShiPlayerDto.setChannelNo(vo.getChannelNo());
                yingShiPlayerDto.setDeviceSerial(vo.getDeviceNo());

                YingShiUrlVo yingShiUrlVo = yingShiUtils.getPlayUrl(yingShiPlayerDto);

                YingShiPlayerVo yingShiPlayerVo = new YingShiPlayerVo();
                yingShiPlayerVo.setAccessToken(dmcYingShiConfig.getAccessToken());
                yingShiPlayerVo.setCode(vo.getCode());
                yingShiPlayerVo.setUrl(yingShiUrlVo.getUrl());
                yingShiPlayerVo.setChannelNo(vo.getChannelNo());
                yingShiPlayerVo.setChannelName(vo.getChannelName());
                yingShiPlayerVo.setChannelLocation(vo.getChannelLocation());
                if (PublicUtil.isNotEmpty(yingShiUrlVo.getExpireTime())) {
                    yingShiPlayerVo.setExpireTime(DateUtil.dateToString(new Date(yingShiUrlVo.getExpireTime())));
                }

                yingShiPlayerVoList.add(yingShiPlayerVo);
            }
        }

        return yingShiPlayerVoList;
    }

    public Map<Long, Map<Integer, YingShiDeviceCameraVo>> getChannelStatus(List<YingShiMonitorVo> yingShiMonitorVoList) {

        Map<Long, Map<Integer, YingShiDeviceCameraVo>> cameraVoMap = Maps.newHashMap();

        Map<Long, DmcYingShiConfig> configMap = Maps.newHashMap();

        for (YingShiMonitorVo vo : yingShiMonitorVoList) {

            DmcYingShiConfig config = configMap.get(vo.getGroupId());
            if (PublicUtil.isEmpty(config)) {
                config = dmcYingShiConfigService.selectByKey(vo.getGroupId());
                if (PublicUtil.isNotEmpty(config)) {
                    configMap.put(vo.getGroupId(), config);
                }
            }

            if (PublicUtil.isEmpty(config)) {
                continue;
            }

            Map<Integer, YingShiDeviceCameraVo> channelVo = cameraVoMap.get(vo.getDeviceId());
            if (PublicUtil.isEmpty(channelVo)) {

                List<YingShiDeviceCameraVo> yingShiDeviceCameraVoList = yingShiUtils
                        .getDeviceCameraList(config.getAccessToken(), vo.getDeviceNo());

                if (PublicUtil.isNotEmpty(yingShiDeviceCameraVoList)) {
                    Map<Integer, YingShiDeviceCameraVo> yingShiDeviceCameraVoMap =
                            yingShiDeviceCameraVoList.stream().collect(Collectors.toMap(YingShiDeviceCameraVo::getChannelNo, a -> a, (k1, k2) -> k1));

                    cameraVoMap.put(vo.getDeviceId(), yingShiDeviceCameraVoMap);
                }
            }
        }

        return cameraVoMap;
    }
}
